package se581.banker;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import se581.banker.listener.RegistrationListener;
import se581.banker.service.HealthMonitorService;
import se581.banker.service.RegistrationService;
import se581.banker.util.ServerSocketInfo;

/**
 * Main for an AccountSystem Registration Service JVM instance.
 * This also starts the HealthMonitor Service.
 * 
 * 
 * @author mmichalak
 *
 */
public class SimulationRegistrationServiceMain {
	static Logger logger = Logger.getLogger(SimulationRegistrationServiceMain.class.getName());
	
	String instancePortNum = "-1";
	
	RegistrationService regSvc = null;
	HealthMonitorService healthSvc = null;
	
	
	/**
	 * 
	 * @param args 
	 * arg1 = Server Instance 1 UpdateTracker host:port,InquiryTracker host:port
	 * arg2 = Server Instance 2 UpdateTracker host:port,InquiryTracker host:port
	 * ...
	 * argn = Server Instance n UpdateTracker host:port,InquiryTracker host:port
	 */
	public static void main(String[] args) {
		logger.debug("Starting RegistrationListener Instance ");	
		
		SimulationRegistrationServiceMain regSvcMain = new SimulationRegistrationServiceMain();
		
		if (args[0].length() > 0)
			regSvcMain.instancePortNum = args[0];
		else
			logger.error("Registration param port number is missing");

		
		regSvcMain.setupSimulation(regSvcMain, args);
		
		
		try {

			Thread thrRegistrationSvc = new Thread(regSvcMain.regSvc.getRegListener());
			thrRegistrationSvc.setDaemon(true);
			thrRegistrationSvc.start();

			// This will start the HealthListener thread
			regSvcMain.healthSvc = new HealthMonitorService();
			// Set Health Monitor in Reg Service and vice versa...
			regSvcMain.regSvc.setHealthMonitor(regSvcMain.healthSvc);
			regSvcMain.healthSvc.setRegSvc(regSvcMain.regSvc);
			
			// This sets the Maps of servers and monitor threads for the HealthService
			regSvcMain.healthSvc.setServerStatus( regSvcMain.createServerStatusMap( regSvcMain.regSvc.getUpdateTrackers() ) );
			regSvcMain.healthSvc.setListenerThreads( new HashMap<ServerSocketInfo, Thread>() );
			regSvcMain.healthSvc.startHealthService();

		} catch (NumberFormatException e) {
			logger.error("Illegal port number:  " + regSvcMain.instancePortNum);
			e.printStackTrace();
		} 
		
		// Sleep Loop to keep server alive
		 try {
		        while (true) {
		            Thread.sleep(5 * 1000);
		        }
		 } catch (InterruptedException e) {
		        e.printStackTrace();
		 }

		logger.debug("Ending RegistrationListener Instance ");
	}
	
	
	/**
	 * Create all the system objects and set relationships
	 */
	void setupSimulation(SimulationRegistrationServiceMain regSvcMain, String[] args) {
		RegistrationService regSvc = new RegistrationService();
		
		regSvcMain.regSvc = regSvc;
	
		// Set the Update and Inq socket server info in the RegistrationService
		parseServerPortInfo(args);

		RegistrationListener regListener = new RegistrationListener();
		regListener.setSocketPort(Integer.parseInt(regSvcMain.instancePortNum));
		regSvcMain.regSvc.setRegListener(regListener);
		
		regListener.setRegSvc(regSvc);

	}
	
	/**
	 * Servers in are update,inquiry pairs.  Each arg[i] is a new server pair
	 * @param args
	 */
	public void parseServerPortInfo(String[] args) {
		List<ServerSocketInfo> updateTrackers = new ArrayList<ServerSocketInfo>();	
		List<ServerSocketInfo> inquiryTrackers = new ArrayList<ServerSocketInfo>();
		
//		// Parse out servers
//		for (int i=0; i < args.length; i++) {
//			
//			// Split in Update Inq pairs
//			String[] pairs = args[i].split(",");
//			ServerSocketInfo updateSvr = new ServerSocketInfo(pairs[0]);
//			updateTrackers.add(updateSvr);
//			ServerSocketInfo inquirySvr = new ServerSocketInfo(pairs[1]);
//			inquiryTrackers.add(inquirySvr);
//			
//		}
//		
		regSvc.setUpdateTrackers(updateTrackers);
		regSvc.setInquiryTrackers(inquiryTrackers);
	}
	
	/**
	 * Create the Map of servers for the HealthMonitor
	 * @param updateTrackers
	 * @return
	 */
	Map<ServerSocketInfo,String> createServerStatusMap(List<ServerSocketInfo> updateTrackers) {
		Map<ServerSocketInfo,String> serverStatus = new HashMap<ServerSocketInfo,String>();
		
//		for (ServerSocketInfo serverPort : updateTrackers) {
//			serverStatus.put(serverPort, BankerConstants.STARTING_STATUS);
//		}
		return serverStatus;
	}
	
}
